using Google.Protobuf;
using System;
using System.Collections.Generic;
public class NetMsgMgr : Singleton<NetMsgMgr>
{
    /// <summary>所有注册响应消息的事件列表</summary>
    public readonly Dictionary<int, LinkedList<Action<object>>> registerList = new Dictionary<int, LinkedList<Action<object>>>();
    
    /// <summary>注册一条服务器响应消息事件，当服务器下发指定类型的消息时，回调函数触发/// </summary>
    /// <param name="msgId">消息类型</param>
    /// <param name="action">回调函数(参数为接收到的服务器的消息)</param>
    /// <param name="allowRepeat">是否允许注册相同的回调函数</param>
    public void RegisterMsg(NetMsgID msgId, Action<object> action, bool allowRepeat = false) {
        int msgID = (int)msgId;
        if (!registerList.ContainsKey(msgID))
            registerList.Add(msgID, new LinkedList<Action<object>>());
        LinkedList<Action<object>> messages = registerList[msgID];
        if (messages.Contains(action) && allowRepeat == false)
            return;
        messages.AddLast(action);
    }
    /// <summary>移除所注册的具体的事件</summary>
    /// <param name="msgId">该事件所属的消息类型</param>
    /// <param name="action">要移除的具体事件</param>
    public void RemoveMsg(NetMsgID msgId, Action<object> action) {
        int msgID = (int)msgId;
        if (registerList.ContainsKey(msgID) && registerList[msgID] != null)
            registerList[msgID].Remove(action);
    }
    /// <summary>移除某一消息类型下所注册的所有事件</summary>
    /// <param name="msgId">消息类型</param>
    public void RemoveMsg(NetMsgID msgId) {
        int msgID = (int)msgId;
        if (registerList.ContainsKey(msgID))
            registerList.Remove(msgID);
    }
    /// <summary>移除所注册的所有事件</summary>
    public void RemoveMsg() {
        registerList?.Clear();
    }
    /// <summary>向服务器发送一条网络消息</summary>
    /// <param name="msgId">消息类型</param>
    /// <param name="message">消息内容</param>
    /// <param name="type">协议类型TCP/UDP</param>
    public void SendMsg(NetMsgID msgId, IMessage message) {
        TCPClient.Instance.SendMessage(msgId, message);
    }

    /// <summary>向该网络事件管理器发送消息, 以触发注册的事件</summary>
    /// <param name="msgId">服务器下发的消息类型</param>
    /// <param name="message">服务器下发的消息内容</param>
    public void RcvMsg(NetMsgID msgId, object message)
    {
        int msgID = (int)msgId;
        registerList.TryGetValue(msgID, out LinkedList<Action<object>> messages);
        if (messages != null)
            foreach (Action<object> callback in messages)
                GameManager.Instance.RunInMainThread(() => callback?.Invoke(message));
    }
}